package com.mikelouis.test.scala.proginscala.chapter9

import java.io.File

/**
 * Created by yuazhu on 1/2/2015.
 */
object FileMatcher {
  private def filesHere = new File(".").listFiles()

  def listFiles() = for (file <- filesHere) println(file.getName)

  def filesEnding(query: String) = for (file <- filesHere if file.getName.endsWith(query)) yield file


  def filesContaining(query: String) = for (file <- filesHere; if file.getName.contains(query)) yield file

  def filesRegex(query: String) = for (file <- filesHere; if file.getName.matches(query)) yield file

  // 不能把方法名当作值传递
  //  def filesMatching(query: String, method) = for (file <- filesHere; if file.getName.method(query)) yield file

  /**
   * 虽然你不能把方法名当作值传递，但你可以通过传递为你调用方法的函数值达到同样的效果
   * 给方法添加一个matcher参数，其唯一的目的就是针对查询检查文件名
   * @param query
   * @param matcher
   * @return
   */
  def filesMatching(query: String, matcher: (String, String) => Boolean) = {
    for (file <- filesHere if matcher(file.getName, query)) yield file
  }

  /** 有了这个新的filesMatching帮助方法，你可以通过让三个搜索方法调用它，并传入合适的函数来简化它们 */
  // _.endsWith(_)和_.contains(_)，都是在运行期实例化成函数值而不是闭包，因为它们没有捕获任何自由变量。
  // 举例来说表达式_.endsWith(_)里用的两个变量，都是用下划线代表的，也就是说它们都是从传递给函数的参数获得的
  def filesEnding2(query: String) = filesMatching(query, _.endsWith(_))

  def filesEnding2Equiv(query: String) = filesMatching(query, (fileName: String, query: String) => fileName.endsWith(query))

  def filesContaining2(query: String) = filesMatching(query, _.contains(_))

  def filesRegex2(query: String) = filesMatching(query, _.matches(_))

  /** query传递给了filesMatching，但filesMatching没有用查询做任何事只是把它传回给传入的matcher函数. 这个传来传去的过程不是必需的，因为调用者在前面就已经知道了query的内容。你可以同样从filesMatching和matcher中简单地去除query参数 */
  // 里面用到的函数文本_.endsWith(query)，包含一个绑定变量，下划线代表的参数，和一个名为query的自由变量。
  // 仅仅因为Scala支持闭包才使得你可以在最近的这个例子里从filesMatching中去掉query参数，从而更进一步简化了代码
  private def filesMatching(matcher: String => Boolean) = for (file <- filesHere; if matcher(file.getName)) yield file

  def filesEnding3(query: String) = filesMatching(_.endsWith(query))

  def filesContaining3(query: String) = filesMatching(_.contains(query))

  def filesRegex3(query: String) = filesMatching(_.matches(query))

}
